# Catnip Go Server Development

# Configuration
GOLANGCI_LINT_VERSION := "2.3.0"

# Build the unified catnip binary
build: swagger build-frontend build-scripts
	#!/usr/bin/env bash
	set -euo pipefail

	# Get the latest git tag (version) - try multiple strategies
	if LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null); then
		# Found a reachable tag
		VERSION="${LATEST_TAG}-dev"
	elif LATEST_TAG=$(git tag --sort=-version:refname | head -1 2>/dev/null) && [ -n "$LATEST_TAG" ]; then
		# Use the highest version tag available, even if not reachable
		VERSION="${LATEST_TAG}-dev-unreachable"
	else
		# No tags found at all
		VERSION="v0.0.0-dev"
	fi

	# Get git commit info
	COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
	DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

	echo "Building catnip ${VERSION} (commit: ${COMMIT})"

	# Enable CGO on macOS for native notifications
	if [[ "$(uname)" == "Darwin" ]]; then
		export CGO_ENABLED=1
		echo "CGO enabled for macOS native notifications"
	else
		export CGO_ENABLED=0
	fi

	go build -ldflags "\
		-X main.version=${VERSION} \
		-X main.commit=${COMMIT} \
		-X main.date=${DATE} \
		-X main.builtBy=just" \
		-o bin/catnip cmd/cli/main.go

	# Create app bundle on macOS
	if [[ "$(uname)" == "Darwin" ]]; then
		just create-app-bundle "${VERSION}"
	fi

	# Restore placeholder frontend assets after building
	just restore-placeholder

# Legacy alias for build
build-cli: build

# Run the server
run: build
	./bin/catnip serve

# Development mode with hot reload (local)
dev:
	air

# Development mode without Air (simple)
dev-simple:
	go run cmd/cli/main.go serve

# Generate Swagger documentation
swagger:
	swag init -g internal/cmd/serve.go -o docs --parseDependency --parseInternal

# Run unit tests (excludes integration tests)
test:
	go test -v ./...

# Run integration tests (requires test container)
test-integration:
	go test -v -tags=integration ./test/integration/...

# Clean build artifacts
clean:
	rm -rf bin/

golangci-lint:
	#!/usr/bin/env bash
	set -euo pipefail

	# Check if golangci-lint is installed and has the correct version
	if command -v golangci-lint >/dev/null 2>&1; then
		INSTALLED_VERSION=$(golangci-lint --version | grep -o 'version [0-9]\+\.[0-9]\+\.[0-9]\+' | cut -d' ' -f2)
		if [ "$INSTALLED_VERSION" = "{{GOLANGCI_LINT_VERSION}}" ]; then
			echo "golangci-lint v{{GOLANGCI_LINT_VERSION}} is already installed"
			exit 0
		else
			echo "golangci-lint v$INSTALLED_VERSION is installed, but we need v{{GOLANGCI_LINT_VERSION}}"
		fi
	else
		echo "golangci-lint is not installed"
	fi

	echo "Installing golangci-lint v{{GOLANGCI_LINT_VERSION}}..."
	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v{{GOLANGCI_LINT_VERSION}}

# Install dependencies
deps: golangci-lint
	go mod download
	go mod tidy
	# Install tools defined in tools.go
	go install github.com/air-verse/air
	go install github.com/swaggo/swag/cmd/swag

# Format code
#fmt:
#	go fmt ./...

# Format all Go files with gofmt
format-go:
	echo "Disabled global gofmt until we start enforcing..."
	# gofmt -w -s .

# Format only changed Go files
format-go-changed:
	#!/usr/bin/env bash
	set -euo pipefail
	# Get staged, changed, and untracked Go files (from repo root, filter for container/)
	files=$({ git diff --cached --name-only --diff-filter=ACMR; git diff --name-only --diff-filter=ACMR; git ls-files --others --exclude-standard; } | grep -E '^container/.*\.go$' | sed 's|^container/||' || true)
	if [ -n "$files" ]; then
		echo "$files" | xargs gofmt -w -s
	else
		echo "No changed Go files to format in container/"
	fi

# Lint code
lint: golangci-lint
	golangci-lint run


# All-in-one development setup
setup: deps swagger build
	@echo "✅ Catnip is ready for development!"

# Build frontend assets
build-frontend:
	#!/usr/bin/env bash
	set -euo pipefail
	
	# Check if we need to rebuild by comparing timestamps
	cd ..
	
	# Check if any source files are newer than the dist directory
	NEEDS_REBUILD=false
	if [ ! -d "dist" ] || [ -z "$(ls -A dist 2>/dev/null)" ]; then
		NEEDS_REBUILD=true
	else
		# Check if any source files are newer than the dist directory
		if find src/ public/ package.json pnpm-lock.yaml vite.config.ts tsconfig*.json -newer dist/ -type f 2>/dev/null | grep -q .; then
			NEEDS_REBUILD=true
		fi
	fi
	
	if [ "$NEEDS_REBUILD" = true ]; then
		echo "Source files are newer than dist, building frontend assets..."
		pnpm install --frozen-lockfile
		
		# Use fast build if TypeScript files haven't changed, full build otherwise
		if find src/ -name "*.ts" -o -name "*.tsx" -newer dist/ 2>/dev/null | grep -q .; then
			echo "TypeScript files changed, running full build..."
			pnpm build
		else
			echo "No TypeScript changes, running fast build..."
			pnpm build:fast
		fi
		
		echo "Copying frontend assets to internal/assets/dist..."
		mkdir -p container/internal/assets/dist
		if [ -d "dist" ]; then cp -r dist/* container/internal/assets/dist/; else echo "Warning: dist directory not found"; fi
		echo "✅ Frontend assets built and copied"
	else
		echo "Dist is up to date, skipping build..."
		# Still ensure the assets are copied to the container location
		mkdir -p container/internal/assets/dist
		if [ -d "dist" ]; then cp -r dist/* container/internal/assets/dist/; else echo "Warning: dist directory not found"; fi
		echo "✅ Frontend assets copied (no rebuild needed)"
	fi

# Build proxy injection script
build-scripts:
	#!/usr/bin/env bash
	set -euo pipefail
	echo "Building proxy injection script..."
	mkdir -p internal/assets/scripts
	cd scripts && pnpm run build
	echo "✅ Proxy injection script built"

# Restore placeholder frontend assets (cleanup after build)
restore-placeholder:
	#!/usr/bin/env bash
	set -euo pipefail
	echo "Restoring placeholder frontend assets..."
	
	# Restore the placeholder index.html from git
	if git show main:container/internal/assets/dist/index.html > internal/assets/dist/index.html 2>/dev/null; then
		echo "✅ Restored placeholder index.html from main branch"
	else
		echo "⚠️  Could not restore from git, using current version (already restored)"
	fi
	
	# Remove any other built frontend assets that shouldn't be in git
	find internal/assets/dist -name "*.js" -delete 2>/dev/null || true
	find internal/assets/dist -name "*.css" -delete 2>/dev/null || true
	find internal/assets/dist -name "assets" -type d -exec rm -rf {} + 2>/dev/null || true
	
	echo "✅ Placeholder assets restored"

# Create macOS app bundle using static structure
create-app-bundle VERSION:
	#!/usr/bin/env bash
	set -euo pipefail
	
	if [[ "$(uname)" != "Darwin" ]]; then
		echo "App bundle creation is only supported on macOS"
		exit 1
	fi
	
	VERSION="{{VERSION}}"
	echo "Creating macOS app bundle for version ${VERSION} using static structure"
	
	# Use static app bundle structure
	STATIC_APP="build/Catnip.app"
	APP_DIR="bin/Catnip.app"
	
	# Remove old dynamic bundle and copy static structure
	rm -rf "${APP_DIR}"
	cp -R "${STATIC_APP}" "${APP_DIR}"
	
	# Copy binary to app bundle
	cp "bin/catnip" "${APP_DIR}/Contents/MacOS/catnip"
	
	# Process Info.plist template to set version
	sed "s/__VERSION__/${VERSION}/g" "${STATIC_APP}/Contents/Info.plist" > "${APP_DIR}/Contents/Info.plist"
	
	# Create a wrapper script for CLI usage
	cat > "bin/catnip-cli" << 'EOF'
	#!/bin/bash
	# Catnip CLI wrapper - calls the binary inside the app bundle
	DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
	exec "${DIR}/Catnip.app/Contents/MacOS/catnip" "$@"
	EOF
	chmod +x "bin/catnip-cli"
	
	echo "✅ Static app bundle deployed to ${APP_DIR}"
	echo "✅ CLI wrapper created at bin/catnip-cli"

# Install catnip locally (macOS only, uses built assets)
install: build
	#!/usr/bin/env bash
	set -euo pipefail

	echo "📦 Installing catnip locally..."
	INSTALL_DIR="${INSTALL_DIR:-${HOME}/.local/bin}"
	mkdir -p "$INSTALL_DIR"
	
	if [[ "$(uname)" != "Darwin" ]]; then
		cp bin/catnip "${INSTALL_DIR}/catnip"
		echo "✅ catnip installed to ${INSTALL_DIR}/catnip"
		exit 0
	fi
	
	# Configuration
	APP_SUPPORT_DIR="${HOME}/Library/Application Support/catnip"
	APP_BUNDLE_PATH="${APP_SUPPORT_DIR}/Catnip.app"
	
	# Check if app bundle was built
	if [[ ! -d "bin/Catnip.app" ]]; then
		echo "❌ App bundle not found at bin/Catnip.app"
		echo "   Run 'just build' first"
		exit 1
	fi
	
	# Create directories
	echo "📁 Creating directories..."
	mkdir -p "$APP_SUPPORT_DIR"
	
	# Clean up old installations
	if [[ -d "$APP_BUNDLE_PATH" ]]; then
		echo "🧹 Removing existing app bundle..."
		rm -rf "$APP_BUNDLE_PATH"
	fi
	
	# Clean up old app bundle from incorrect location (if it exists)
	OLD_APP_LOCATION="$INSTALL_DIR/Catnip.app"
	if [[ -d "$OLD_APP_LOCATION" ]]; then
		echo "🧹 Cleaning up old app bundle from $INSTALL_DIR..."
		rm -rf "$OLD_APP_LOCATION"
	fi
	
	# Install app bundle to Application Support
	echo "📱 Installing app bundle to Application Support..."
	cp -R "bin/Catnip.app" "$APP_BUNDLE_PATH"
	
	# Create CLI wrapper in install directory
	echo "🔧 Creating CLI wrapper..."
	cat > "$INSTALL_DIR/catnip" << EOF
	#!/bin/bash
	# Catnip CLI wrapper - calls the binary inside the app bundle
	exec "${APP_BUNDLE_PATH}/Contents/MacOS/catnip" "\$@"
	EOF
	
	chmod +x "$INSTALL_DIR/catnip"
	
	# Verify installation
	echo "✅ Installation complete!"
	echo ""
	echo "📍 App bundle: $APP_BUNDLE_PATH"
	echo "📍 CLI wrapper: $INSTALL_DIR/catnip"
	
	# Check if install directory is in PATH
	if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
		echo ""
		echo "⚠️  $INSTALL_DIR is not in your PATH"
		echo "   Add it by adding this line to your shell profile:"
		echo "   export PATH=\"$INSTALL_DIR:\$PATH\""
	else
		echo ""
		echo "🎉 You can now run: catnip --help"
		
		# Try to get version
		if command -v catnip >/dev/null 2>&1; then
			VERSION=$(catnip --version 2>/dev/null || catnip version 2>/dev/null || echo "unknown")
			echo "   Installed version: $VERSION"
		fi
	fi

# Show available commands
default:
	@just --list
